import gugga.events.EventDispatcher;
import mx.utils.Delegate;

import gugga.collections.HashTable;
import gugga.debug.Assertion;
import gugga.navigation.INavigation;
import gugga.utils.Locker;

[Event("markNavigation")]

/**
 * @author Todor Kolev
 */
class gugga.application.NavigationManager extends EventDispatcher
{
	private var mNavigationLocker : Locker;
	private var mNavigations : HashTable;
	
	private var mLastMarkedSectionPath : String;
	public function get LastMarkedSectionPath() : String { return mLastMarkedSectionPath; }
	public function set LastMarkedSectionPath(aValue:String) : Void { mLastMarkedSectionPath = aValue; }
	
	private static var mInstance : NavigationManager;
	public static function get Instance() : NavigationManager 
	{ 
		if(!mInstance)
		{
			mInstance = new NavigationManager();
		}
		
		return mInstance; 
	}
	
	public function NavigationManager() 
	{
		mNavigationLocker = new Locker();
		mNavigations = new HashTable();
		
		mNavigationLocker.addEventListener("locked", Delegate.create(this, onNavigationLocked));
		mNavigationLocker.addEventListener("unlocked", Delegate.create(this, onNavigationUnlocked));
	}
	
	public function registerNavigation(aNavigation:INavigation, aID:String) : Void
	{
		Assertion.failIfContainsKey(mNavigations, aID, "Navigation with this ID is already registered", this, arguments);
		mNavigations[aID] = aNavigation;
		
		if(mLastMarkedSectionPath)
		{
			//TODO: check if Navigation is started
			aNavigation.selectSubItemsPointingTo(mLastMarkedSectionPath);
		}
	}
	
	public function unregisterNavigation(aID:String) : Void
	{
		mNavigations.remove(aID);
	}

	public function unregisterNavigationInstance(aNavigation:INavigation) : Void
	{
		var id : String = mNavigations.getKeyByValue(aNavigation);
		mNavigations.remove(id);
	}
	
	public function setNavigationLock(aLockID:String) : String
	{
		return mNavigationLocker.setLock(aLockID);
	}
	
	public function clearNavigationLock(aLockID:String) : Void
	{
		mNavigationLocker.clearLock(aLockID);
	}

	public function clearAllNavigationLocks() : Void
	{
		mNavigationLocker.clearAllLocks();
	}

	public function markNavigations(aSectionPath:String) : Void
	{
		mLastMarkedSectionPath = aSectionPath;
		
		var navigation : INavigation;
		for (var key:String in mNavigations)
		{
			navigation = INavigation(mNavigations[key]);
			if(navigation)
			{
				navigation.selectSubItemsPointingTo(aSectionPath);
			}
			else
			{
				mNavigations.remove(key);
			}	
		}
		
		dispatchEvent({type: "markNavigation", target: this, sectionPath: aSectionPath});
	}
	
	/*
	 * TODO: this method should be removed. Each navigation can be started separetly.
	 */
	public function startNavigations()
	{
		for (var key:String in mNavigations)
		{
			INavigation(mNavigations[key]).start();	
		}
	}
	
	public function isNavigationEnabled()
	{
		mNavigationLocker.isLocked();
	}
	
	private function onNavigationLocked(ev) : Void 
	{
		for (var key:String in mNavigations)
		{
			INavigation(mNavigations[key]).disable();	
		}
	}

	private function onNavigationUnlocked(ev) : Void 
	{
		for (var key:String in mNavigations)
		{
			INavigation(mNavigations[key]).enable();	
		}
	}
}